package com.inspur.edp.cef.designtime.api.collection;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.inspur.edp.cef.designtime.api.IFieldCollection;
import com.inspur.edp.cef.designtime.api.IGspCommonDataType;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.cef.designtime.api.util.DataValidator;
import com.inspur.edp.cef.designtime.api.element.GspAssociation;
import java.util.ArrayList;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;

/**
 * The Collection Of FieldDefinition
 *
 * @ClassName: GspFieldCollection
 * @Author: Benjamin Gong
 * @Date: 2021/1/11 17:13
 * @Version: V1.0
 */
public class GspFieldCollection extends BaseList<IGspCommonField> implements IFieldCollection {
	private static final long serialVersionUID = 1L;
	@JsonIgnore
	private HashMap<String,IGspCommonField> gspCommonFieldMap;
	private HashMap<String,IGspCommonField> gspCommonFieldMapWithoutLower;
	// @JsonIgnore
	private IGspCommonDataType parentObject;

	public GspFieldCollection() {
		gspCommonFieldMap = new HashMap<>();
		gspCommonFieldMapWithoutLower = new HashMap<>();
	}

	/**
	 * 创建字段集合
	 * 
	 * @param parentObj
	 */
	public GspFieldCollection(IGspCommonDataType parentObj) {
		parentObject = parentObj;
		gspCommonFieldMap = new HashMap<>();
		gspCommonFieldMapWithoutLower = new HashMap<>();
	}

	/**
	 * 移动字段
	 * 
	 * @param toIndex 目的索引为止
	 * @param element 需要移动的字段
	 */
	public final void move(int toIndex, IGspCommonField element) {
		if (contains(element)) {
			super.remove(element);
			super.add(toIndex, element);
		}
	}

	public final void remove(String id){
		IGspCommonField field = getByID(id);
		if(field != null)
			super.remove(field);
	}
	/**
	 * 克隆
	 * 
	 * @param absObject
	 * @param parentAssociation
	 * @return
	 */
	public GspFieldCollection clone(IGspCommonDataType absObject, GspAssociation parentAssociation) {
		GspFieldCollection newCollection = new GspFieldCollection(absObject);
		for (IGspCommonField item : this) {
			newCollection.add(item.clone(absObject, parentAssociation));
		}
		return newCollection;
	}

	///// <summary>
	///// Index[string]
	///// </summary>
	public IGspCommonField getItem(String id) {
		for (IGspCommonField item : this) {
			if (id.equals(item.getID())) {
				return item;
			}
		}
		return null;
	}

	protected final IGspCommonField getByID(String id) {
		for (IGspCommonField item : this) {
			if (id.equals(item.getID())) {
				return item;
			}
		}
		return null;
	}

	protected final IGspCommonField getByIndex(int index) {
		return super.get(index);
	}

	/**
	 * 所属结点
	 * 
	 */
	public IGspCommonDataType getParentObject() {
		return parentObject;
	}

	public final void setParentObject(IGspCommonDataType value) {
		if (parentObject != value) {
			parentObject = value;
			for (IGspCommonField item : this) {
				item.setBelongObject(value);
			}
		}
	}

	public IGspCommonField getItem(int index) {
		return super.get(index);
	}

	// private void setItem(int index, IGspCommonField value) {
	// super.set(index, value);
	// }

	/**
	 * 添加一个新字段
	 * 
	 * @param element
	 */
	@Override
	public boolean add(IGspCommonField element) {
		DataValidator.checkForNullReference(element, "element");

		boolean result = super.add(element);
		if (getParentObject() != null) {
			element.setBelongObject(getParentObject());
		}
		gspCommonFieldMap.put(element.getLabelID().toLowerCase(),element);
		gspCommonFieldMapWithoutLower.put(element.getLabelID(),element);
		return result;
	}
	@Override
	public void add(int index, IGspCommonField element){
		super.add(index,element);
		gspCommonFieldMap.put(element.getLabelID().toLowerCase(),element);
		gspCommonFieldMapWithoutLower.put(element.getLabelID(),element);
	}
	@Override
	public boolean addAll(Collection<? extends IGspCommonField> c) {
		c.forEach(element->{
			gspCommonFieldMap.put(element.getLabelID().toLowerCase(),element);
			gspCommonFieldMapWithoutLower.put(element.getLabelID(), element);
		});
		return super.addAll(c);
	}

	@Override
	public boolean addAll(int index, Collection<? extends IGspCommonField> c){
		c.forEach(element->{
			gspCommonFieldMap.put(element.getLabelID().toLowerCase(),element);
			gspCommonFieldMapWithoutLower.put(element.getLabelID(), element);
		});
		return super.addAll(index,c);
	}

	@Override
	public boolean remove(Object element){
		if(element instanceof IGspCommonField){
			gspCommonFieldMap.remove(((IGspCommonField)element).getLabelID().toLowerCase());
			gspCommonFieldMapWithoutLower.remove(((IGspCommonField)element).getLabelID());
		}
		return super.remove(element);
	}

	@Override
	public IGspCommonField remove(int index){
		IGspCommonField result = super.remove(index);
		gspCommonFieldMap.remove(result.getLabelID().toLowerCase());
		gspCommonFieldMapWithoutLower.remove(result.getLabelID());
		return result;
	}
	@Override
	public boolean removeAll(Collection<?> elements){
		Objects.requireNonNull(elements);
		elements.forEach(element->{
			if(element instanceof IGspCommonField){
				gspCommonFieldMap.remove(((IGspCommonField)element).getLabelID().toLowerCase());
				gspCommonFieldMapWithoutLower.remove(((IGspCommonField)element).getLabelID());
			}
		});
		return super.removeAll(elements);
	}

	@Override
	public boolean removeIf(Predicate<? super IGspCommonField> filter){
		boolean result = super.removeIf(filter);
		final Iterator<IGspCommonField> each = this.iterator();
		while (each.hasNext()) {
				gspCommonFieldMap.remove(((IGspCommonField)each).getLabelID().toLowerCase());
				gspCommonFieldMapWithoutLower.remove(((IGspCommonField)each).getLabelID());
		}
		return result;
	}

	@Override
	public boolean retainAll(Collection<?> elements){
		boolean result = super.retainAll(elements);
		Objects.requireNonNull(elements);
		elements.forEach(element->{
			if(element instanceof IGspCommonField){
				gspCommonFieldMap.remove(((IGspCommonField)element).getLabelID().toLowerCase());
				gspCommonFieldMapWithoutLower.remove(((IGspCommonField)element).getLabelID());
			}
		});
		return result;
	}

	@Override
	public void replaceAll(UnaryOperator<IGspCommonField> operator){
		super.replaceAll(operator);
		gspCommonFieldMap.clear();
		for(IGspCommonField element : this){
			gspCommonFieldMap.put(element.getLabelID().toLowerCase(),element);
			gspCommonFieldMapWithoutLower.put(element.getLabelID(), element);
		}
	}

	@Override
	public IGspCommonField set(int index, IGspCommonField element) {
		IGspCommonField result = super.set(index, element);
		gspCommonFieldMap.put(element.getLabelID().toLowerCase(),element);
		gspCommonFieldMapWithoutLower.put(element.getLabelID(), element);
		return result;
	}

	@Override
	public void clear(){
		super.clear();
		gspCommonFieldMap.clear();
		gspCommonFieldMapWithoutLower.clear();
	}

	@Override
	public IGspCommonField getByLabelId(String labelId) {
		IGspCommonField targetField = gspCommonFieldMapWithoutLower.get(labelId);
		if(targetField == null) {
			targetField = gspCommonFieldMap.get(labelId.toLowerCase());
		}
		if(targetField == null){
			for(IGspCommonField field: this){
				if(field.getLabelID().equalsIgnoreCase(labelId))
					return field;
			}
		}
		return targetField;
	}
}
